import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.image.*;
import com.sun.j3d.utils.behaviors.vp.*;
import java.io.FileInputStream;
import javax.swing.JFrame;


/**
* Beispiel fuer die Verwendung von Sound. Als Hintergrundklang wird Regen
* verwendet. Ein fliegender Vogel kreischt mit einem PointSound.
* Dieses Programm benoetigt die Dateien bgsound.wav, psound.wav
* und darkclouds.jpg.
*
* @author Frank Klawonn
* Letzte Aenderung 17.07.2005
*/
public class SoundExample extends JFrame
{


  //Der Canvas, auf den gezeichnet wird.
  public Canvas3D myCanvas3D;


  public SoundExample()
  {
    //Mechanismus zum Schliessen des Fensters und beenden des Programms
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    //Standardeinstellung fuer das Betrachteruniversum
    myCanvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());


    //Aufbau des SimpleUniverse:
    //Zuerst Erzeugen zusammen mit dem Canvas
    SimpleUniverse simpUniv = new SimpleUniverse(myCanvas3D);


    //Standardpositionierung des Betrachters
    simpUniv.getViewingPlatform().setNominalViewingTransform();


    //Erzeuge das AudioDevice zur Wiedergabe der Sounds
    AudioDevice ad = simpUniv.getViewer().createAudioDevice();


    //Die Szene wird in dieser Methode erzeugt.
    createSceneGraph(simpUniv);


    //Hinzufuegen von Licht
    addLight(simpUniv);


    //Hierdurch kann man mit der Maus den Betrachterstandpunkt veraendern
    OrbitBehavior ob = new OrbitBehavior(myCanvas3D);
    ob.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE));
    simpUniv.getViewingPlatform().setViewPlatformBehavior(ob);


    //Darstellung des Canvas/Fensters:
    setTitle("Background- und Point-Sound");
    setSize(1000,700);
    getContentPane().add("Center", myCanvas3D);
    setVisible(true);


  }




  public static void main(String[] args)
  {
     SoundExample be = new SoundExample();
  }





  //In dieser Methode werden die Objekte der Szene aufgebaut und dem
  //SimpleUniverse su hinzugefuegt.
  public void createSceneGraph(SimpleUniverse su)
  {

    //Das Laden der Sounds etc.
    MediaContainer soundMC;
    MediaContainer pointMC;
    PointSound soundPoint = new PointSound();
    BackgroundSound soundBG = new BackgroundSound();
    try
    {
      FileInputStream bgis = new FileInputStream("bgsound.wav");
      FileInputStream pointis = new FileInputStream("psound.wav");
      soundMC = new MediaContainer(bgis);
      pointMC = new MediaContainer(pointis);
      soundBG.setSoundData(soundMC);
      soundPoint.setSoundData(pointMC);
    }
    catch(Exception e)
    {
      System.out.println("Es gab Probleme beim Laden der Sound-Dateien.");
    }


    soundBG.setEnable(true);
    soundBG.setLoop(Sound.INFINITE_LOOPS);
    soundBG.setInitialGain(0.9f);

    soundPoint.setEnable(true);
    soundPoint.setLoop(Sound.INFINITE_LOOPS);
    soundPoint.setInitialGain(0.6f);



    BoundingSphere sbounds = new BoundingSphere (new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
    soundBG.setSchedulingBounds(sbounds);
    soundPoint.setSchedulingBounds(sbounds);


    //Die Farben fuer die Appearance des Vogels
    Color3f ambientColourBird = new Color3f(0.0f,0.0f,0.0f);
    Color3f emissiveColourBird = new Color3f(0.0f,0.0f,0.0f);
    Color3f diffuseColourBird = new Color3f(0.1f,0.1f,0.1f);
    Color3f specularColourBird = new Color3f(0.1f,0.1f,0.1f);
    float shininessBird = 10.0f;



    //Die Appearance des Vogels
    Appearance birdApp = new Appearance();
    birdApp.setMaterial(new Material(ambientColourBird,emissiveColourBird,
                          diffuseColourBird,specularColourBird,shininessBird));

    //Die Fluegel
    Box wings = new Box(0.03f,0.005f,0.3f,birdApp);

    //Die Transformationsgruppe fuer den Vogel mit Bewegung und Sound
    TransformGroup tgmBird = new TransformGroup();
    tgmBird.addChild(wings);

    //Der Koerper des Vogels
    Box body = new Box(0.1f,0.01f,0.01f,birdApp);
    tgmBird.addChild(body);


    //Der Vogelflug
    long flightTime = 10000;
    Alpha flightAlpha = new Alpha(-1,Alpha.INCREASING_ENABLE+Alpha.DECREASING_ENABLE,
                                  0,0,flightTime,0,0,flightTime,0,0);

    float flightDistance = 9.0f;
    PositionInterpolator posIFlight = new PositionInterpolator(flightAlpha,
                                                   tgmBird,new Transform3D(),
                                                   0.0f,flightDistance);

    BoundingSphere bs = new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
    posIFlight.setSchedulingBounds(bs);

    tgmBird.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    tgmBird.addChild(posIFlight);

    //Fuege den PointSound ebenfalls zur Transformationsgruppe des Vogels
    tgmBird.addChild(soundPoint);


    //Eine Transformationsgruppe, um den Vogelflug nach oben und hinten zu verschieben.
    Transform3D tfBird = new Transform3D();
    tfBird.setTranslation(new Vector3f(-flightDistance/2,1.7f,-5.0f));
    TransformGroup tgBird = new TransformGroup(tfBird);
    tgBird.addChild(tgmBird);


    //Fuege alles zur Szene hinzu
    BranchGroup theScene = new BranchGroup();
    theScene.addChild(tgBird);


    //Der Wirkungsbereich fuer den Hintergrund
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE);
    //Lade das Hintergrundbild
    TextureLoader textureLoad = new TextureLoader("darkclouds.jpg",null);
    //Definiere das Bild als Hintergrund und fuege den Hintergrund zur Szene
    Background bgImage = new Background(textureLoad.getImage());
    bgImage.setApplicationBounds(bounds);
    theScene.addChild(bgImage);

    //Fuege den Hintergrundklang (Regen) zur Szene hinzu.
    theScene.addChild(soundBG);

    theScene.compile();

    //Hinzufuegen der Szene
    su.addBranchGraph(theScene);

  }






  //Hier wird etwas Licht zu der Szene hinzugefuegt.
  public void addLight(SimpleUniverse su)
  {

    BranchGroup bgLight = new BranchGroup();

    //Direktionales Licht
    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);
    Color3f lightColour1 = new Color3f(1.0f,1.0f,1.0f);
    Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.1f);
    DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
    light1.setInfluencingBounds(bounds);

    bgLight.addChild(light1);


    //Streulicht
    Color3f ambientLightColour = new Color3f(0.5f, 0.5f, 0.5f);
    AmbientLight ambLight = new AmbientLight(ambientLightColour);
    ambLight.setInfluencingBounds(bounds);
    bgLight.addChild(ambLight);



    su.addBranchGraph(bgLight);

  }



}
